package com.java.sjzl.controller;

import com.java.sjzl.entity.ClassDTO;
import com.java.sjzl.frame.IgnoreExportField;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

public class ApachePoiExcelSimple {

    public static void main(String[] args) throws IOException {
        String outputPath =getOutPath();
        List<ClassDTO> listDTO=loadData();
        String title="测试表1";
        List<String> tableHead=constructColumnTitles();
        createExcel(outputPath,listDTO,title,tableHead);
        System.out.println("导出"+title+"成功！");


    }
    //模拟前端传入的报表数据内容
    public static List<ClassDTO> loadData() {
        List<ClassDTO> list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            ClassDTO class1 = new ClassDTO();
            class1.setClassNo("20200" + i);
            class1.setClassTeacher("老师" + i);
            class1.setClassSlogan("班级口号" + i);
            class1.setBoyNum(30 + i % 3);
            class1.setGirlNum(20 + i % 2);
            list.add(class1);
        }
        return list;
    }

    //模拟前端传入的表格头
    private static List<String> constructColumnTitles() {
        //这个可以根据前端报表行选择列头传入
        List<String> list = new ArrayList<>();
        list.add("班级编号");
        list.add("班主任");
        list.add("班级口号");
        list.add("男生人数");
        list.add("女生人数");
        return list;
    }

    public static String getOutPath() {
        //设置导出路径
        StringBuilder sb = new StringBuilder(System.getProperty("user.dir") + "/src/main/resources/export/");
//        sb.append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
//        sb.append("/");
        return sb.toString();
    }

    /**
     * 导出报表
     * @param outputPath 导出路径
     * @param listDTO 传入的数据
     * @param title 报表标题
     * @param tableHead 表头
     * @param <T>
     * @throws IOException
     */
    public static <T> void createExcel(String outputPath, List<T> listDTO, String title, List<String> tableHead) throws IOException {
        //验证数据....

        //创建工作簿
        XSSFWorkbook workBook = new XSSFWorkbook();
        //定义行
        int currentRowIndex = 0;
        //创建一个单元格 当做标题
        XSSFSheet sheet = workBook.createSheet();

        //设置标题和标题格式
        if (StringUtils.isNotBlank(title)) {
            //合并单元格
            sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, tableHead.size() - 1));
            // 创建表格行，设置总标题
            XSSFRow totalTitleRow = sheet.createRow(currentRowIndex);
            totalTitleRow.createCell(currentRowIndex).setCellValue(title);

            XSSFCellStyle cellStyle = totalTitleRow.getCell(0).getCellStyle();
            //总标题列内容居中
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            //总标题行样式
            XSSFCellStyle style = workBook.createCellStyle();
            //垂直居中
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            //右对齐
            style.setAlignment(HorizontalAlignment.RIGHT);
            totalTitleRow.setRowStyle(style);
            //填充完了行数记得+1
            currentRowIndex++;
        }

        //创建表格【列标题】行
        XSSFRow titleRow = sheet.createRow(currentRowIndex);
        for (int j = 0; j < tableHead.size(); j++) {
            titleRow.createCell(j).setCellValue(tableHead.get(j));
        }
        currentRowIndex++;

        if (CollectionUtils.isNotEmpty(listDTO)) {
            //创建数据行
            int cellIndex;
            for (T t : listDTO) {
                cellIndex = 0;
                XSSFRow row = sheet.createRow(currentRowIndex++);
                //通过获取类中的字段（包括父类）
                Field[] fieldList = getFieldsFromClass(null, t.getClass());
                if (ArrayUtils.isEmpty(fieldList))
                    return;
                //循环出所有导出列
                for (int j = 0; j < fieldList.length; j++) {
                    Field field = fieldList[j];
                    if (field.isSynthetic())
                        continue;
                    //扫描注解 如果有这个注解的话 单元格+1
                    IgnoreExportField annotation = field.getAnnotation(IgnoreExportField.class);
                    if (annotation != null) {
                        cellIndex++;
                        continue;
                    }
                    //填充数据
                    try {
                        field.setAccessible(true);
                        Object o = field.get(t);
                        XSSFCell cell = row.createCell(cellIndex++);
                        if (o != null) {
                            if (o instanceof Long) {
                                cell.setCellValue((long) o);
                            } else if (o instanceof Integer) {
                                cell.setCellValue((int) o);
                            } else if (o instanceof Double)
                                cell.setCellValue((double) o);
                            else if (o instanceof BigDecimal)
                                cell.setCellValue(((BigDecimal) o).doubleValue());
                            else
                                cell.setCellValue(String.valueOf(o));
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }


            FileOutputStream outStream = null;
            try {
                //判断输出的文件夹是否存在，不存在，则创建
                File file = new File(outputPath);
                if (!file.exists())
                    file.mkdirs();
                //创建导出文件
                file = File.createTempFile("测试表"+LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH-mm-ss")), ".xlsx", file);
                outStream = new FileOutputStream(file);
                workBook.write(outStream);
                outStream.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (outStream != null) {
                    outStream.close();
                }
            }
        }
    }
    /**
     * 获取类中的所有字段(包括父类)
     * @param fieldList
     * @param clazz
     * @return
     */
    private static Field[] getFieldsFromClass(Field[] fieldList, Class<?> clazz) {
        if (clazz == null) {
            return fieldList;
        }
        Field[] fieldArray = clazz.getDeclaredFields();
        if (fieldList != null) {
            fieldArray = ArrayUtils.addAll(fieldList, fieldArray);
        }
        fieldArray = getFieldsFromClass(fieldArray, clazz.getSuperclass());
        return fieldArray;
    }




}
